package com.spzx.cart.service.impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.vo.ProductSkuVo;
import com.spzx.product.api.vo.SkuPriceVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements ICartService {

    @Autowired
    private RemoteProductService remoteProductService;

    @Autowired
    private RedisTemplate redisTemplate;

    private String getCartKey(Long userId) {
        //定义key user:cart:userId
        return "user:cart:" + userId;
    }

    @Override
    public void addToCart(Long skuId, Integer skuNum) {

//从redis中获取购物车列表，查询skuId在列表中是否存在，如果不存在则创建CartInfo对象
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        //1.构建“用户”购物车hash结构key  user:cart:用户ID
        String cartKey = getCartKey(userId);

        //2.创建Hash结构绑定操作对象（方便对hash进行操作）
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        String hashKey = skuId.toString();
        Integer threshold = 9;
        if (hashOps.hasKey(hashKey)) {
            CartInfo cartInfo = hashOps.get(hashKey);
            int totalCount = cartInfo.getSkuNum() + skuNum;
            cartInfo.setSkuNum(totalCount > threshold ? threshold : totalCount);
            //存入redis
            hashOps.put(hashKey, cartInfo);
        } else {
            //3.判断购物车商品种类（不同SKU）总数大于50件
            Long count = hashOps.size();
            if (++count > 5) {
                throw new RuntimeException("商品种类数量超过上限！");
            }
            R<ProductSkuVo> productSkuVoResult = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if (R.FAIL == productSkuVoResult.getCode()) {
                throw new ServiceException(productSkuVoResult.getMsg());
            }
            ProductSkuVo productSkuVo = productSkuVoResult.getData();

            CartInfo cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuNum(skuNum);
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuName(productSkuVo.getSkuName());
            cartInfo.setCartPrice(productSkuVo.getSalePrice());
            cartInfo.setSkuPrice(productSkuVo.getSalePrice());
            cartInfo.setThumbImg(productSkuVo.getThumbImg());
            cartInfo.setIsChecked(1);
            cartInfo.setCreateTime(new Date());
            //存入redis
            hashOps.put(hashKey, cartInfo);
        }

    }

    @Override
    public List<CartInfo> getCartList() {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            //根据CreateTime降序排列
            cartInfoList.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
            //在购物车列表获取skuIdList
            List<Long> skuIdList = cartInfoList.stream().map(CartInfo::getSkuId).toList();
            R<List<SkuPriceVo>> skuPriceListResult = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
            if (R.FAIL == skuPriceListResult.getCode()) {
                throw new ServiceException(skuPriceListResult.getMsg());
            }
            List<SkuPriceVo> skuPriceList = skuPriceListResult.getData();
            /*//遍历购物车列表,修改新价格
            for (CartInfo cartInfo : cartInfoList) {
                for (SkuPriceVo skuPriceVo : skuPriceList) {
                    if (skuPriceVo.getSkuId().equals(cartInfo.getSkuId())) {
                        cartInfo.setSkuPrice(skuPriceVo.getSalePrice());
                    }
                }
            }*/
            Map<Long, BigDecimal> priceMap = skuPriceList.stream().collect(Collectors.toMap(SkuPriceVo::getSkuId, SkuPriceVo::getSalePrice));
            for (CartInfo cartInfo : cartInfoList) {
                //修改实时价格
                Long skuId = cartInfo.getSkuId();
                if (cartInfo.getSkuPrice().compareTo(priceMap.get(skuId)) != 0) {
                    cartInfo.setSkuPrice(priceMap.get(skuId));
                    hashOps.put(skuId.toString(), cartInfo);
                }
            }
            return cartInfoList;
        }
        return new ArrayList<>();
    }

    @Override
    public void deleteCart(Long skuId) {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        hashOps.delete(skuId.toString());
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        String hashKey = skuId.toString();
        if (hashOps.hasKey(hashKey)) {
            CartInfo cartInfo = hashOps.get(hashKey);
            cartInfo.setIsChecked(isChecked);
            hashOps.put(hashKey, cartInfo);
        }
    }

    @Override
    public void allCheckCart(Integer isChecked) {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            cartInfoList.forEach(item -> {
                String hashKey = item.getSkuId().toString();
                CartInfo cartInfoUpdate = hashOps.get(hashKey);
                cartInfoUpdate.setIsChecked(isChecked);

                // 更新缓存
                hashOps.put(hashKey, cartInfoUpdate);
            });
        }
    }

    @Override
    public void clearCart() {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        redisTemplate.delete(cartKey);
    }

    @Override
    public List<CartInfo> getCartCheckedList() {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            cartInfoList = cartInfoList
                    .stream()
                    .filter(CartInfo -> CartInfo.getIsChecked() == 1)
                    .toList();
        }
        return cartInfoList;

    }

    @Override
    public Boolean deleteCartCheckedList() {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            cartInfoList.stream().filter(cartInfo -> cartInfo.getIsChecked() == 1).forEach(cartInfo -> {
                hashOps.delete(cartInfo.getSkuId().toString());
            });
        }
        return true;
    }
}
